Repository navigation
refactor(examples): use type-safe handlers and tag validation in 10-production-boilerplate. - #33
hashi-divyansh wants to merge 3 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
3ce95bf to
c6a4f57
Compare
c6a4f57 to
e0c0b53
Compare
kolkov
left a comment
There was a problem hiding this comment.
Thanks @hashi-divyansh — the conversion is right. I checked it merged with current main: the new 422/415 behavior measures as claimed (the table's "was" column is off for Content-Type, see below), success responses keep their statuses and bodies, and SSE (200, text/event-stream) and WebSocket (101) still upgrade through the generic handlers.
Needed before merge:
- internal/user/api.go:54: c.Created("/api/users/me", …) adds Location: /api/users/me, which main never sent; that path is the caller's profile, not the created user (the comment above already says "fix this dummy url"). Use c.Context.Created(ToResponse(user)) or a real URL.
Optional:
- The table's "wrong Content-Type was 400" isn't what main does: valid JSON with text/plain returns 201/200. 415 is correct, just a bigger change than described; no test covers 422/415 yet.
- Two inputs still return 500: a@b.c passes the email tag but fails emailRegex (2+ letter TLD), and a 100-byte password fails in bcrypt. max=72 (see examples/validation/02) and a tag backed by emailRegex, or mapping domain errors to 422, close them.
On CORSOrigins: yes, string — AllowOrigins is a comma-separated string (middleware/cors.go:36) split in buildAllowMap; config.go:41 wraps the whole env value in a one-element slice. It's unused today (main.go uses middleware.CORS()), so wiring it is a separate change.
- register: use Context.Created so no Location header is sent (the previous /api/users/me was not the created user's URL) - Add max=72 to password fields (bcrypt limit), as in examples/validation/02 - Tests: cover 422 (missing email, password too long), 415 (text/plain) and the absence of a Location header on register
|
Thanks for the review, Kolkov. Fixed:
The a@b.c 500 already happens on main (the old Validate() errors also fell through MapError), so I’ll handle it in a follow-up that maps domain validation errors to 422. The CORSOrigins type change and wiring will be a separate PR #40 . |
6459b9e to
224656d
Compare
Summary
Modernizes
examples/10-production-boilerplateto use fursy's type-safe generic handlers (fursy.Box[Req, Res]) and the built-in tag-based validation (plugins/validator), so the "production" example demonstrates fursy's recommended patterns. Business logic is unchanged.Behavior changes (error responses only)
Invalid Request: …Bad RequestMapError)Validation Failed+errorsmapmessageon broadcastMessage is requiredValidation FailedContent-Type(e.g.text/plain)Unsupported Media TypeValidation Failed(max=72)Success responses, routes, methods and status codes are unchanged.
Testing
go mod tidy && go build ./...,go vet ./...,gofmt,go test -race ./...(also verified merged with currentmain)TestAPI_Registercases: missing email → 422, password > 72 characters → 422,text/plain→ 415, and an assertion that register sends noLocationheaderLocationheader), login 200info{}→ 422GET /api/chat/ws→ 101 Switching Protocolsupstream/main: success responses are identical